namespace SimpleWebServices.Data
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Net;
    using System.Web;
    using System.Xml;
    using System.Xml.XPath;
    using SimpleWebServices;
    using Xunit;

    public sealed class XmlDataObjectCollectionFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<XmlDataObjectCollection>()
                .DerivesFrom<Collection<XmlDataObject>>()
                .IsConcreteClass()
                .IsSealed()
                .HasDefaultConstructor()
                .Result);
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new XmlDataObjectCollection());
        }

        [Fact]
        public void op_Add_IEnumerable()
        {
            XmlDataObject[] expected = new XmlDataObject[1]
            {
                new XmlDataObject
                {
                    Urn = "urn://data/object"
                }
            };

            XmlDataObjectCollection actual = new XmlDataObjectCollection();
            actual.Add(expected);

            Assert.Same(expected[0], actual[0]);
        }

        [Fact]
        public void op_Add_IEnumerableNull()
        {
            Assert.Throws<ArgumentNullException>(() => new XmlDataObjectCollection().Add(null as IEnumerable<XmlDataObject>));
        }

        [Fact]
        public void op_Add_DirectoryInfo()
        {
            XmlDataObjectCollection actual = new XmlDataObjectCollection();
            actual.Add(new DirectoryInfo(@"Data"));

            Assert.Equal<int>(2, actual.Count);

            Assert.IsType<XmlDataObject>(actual[0]);
            Assert.Equal<HttpCacheability>(HttpCacheability.Public, actual[0].Cacheability.Value);
            Assert.Equal<HttpStatusCode>(HttpStatusCode.NotFound, actual[0].Status.Value);
            Assert.Equal<Type>(typeof(TestRecord), actual[0].ObjectType);

            Assert.IsType<XmlDataObject>(actual[1]);
            Assert.Equal<HttpCacheability>(HttpCacheability.Public, actual[1].Cacheability.Value);
            Assert.Equal<HttpStatusCode>(HttpStatusCode.OK, actual[1].Status.Value);
            Assert.Equal<Type>(typeof(TestRecord), actual[1].ObjectType);
        }

        [Fact]
        public void op_Add_DirectoryInfoNotFound()
        {
            Assert.Throws<FileNotFoundException>(() => new XmlDataObjectCollection().Add(new DirectoryInfo(Token.New())));
        }

        [Fact]
        public void op_Add_DirectoryInfoNull()
        {
            Assert.Throws<ArgumentNullException>(() => new XmlDataObjectCollection().Add(null as DirectoryInfo));
        }

        [Fact]
        public void op_Add_FileInfo()
        {
            XmlDataObjectCollection actual = new XmlDataObjectCollection();
            actual.Add(new FileInfo(@"Data\Record.Test.object.xml"));

            Assert.Equal<int>(2, actual.Count);

            Assert.IsType<XmlDataObject>(actual[0]);
            Assert.Equal<HttpCacheability>(HttpCacheability.Public, actual[0].Cacheability.Value);
            Assert.Equal<HttpStatusCode>(HttpStatusCode.NotFound, actual[0].Status.Value);
            Assert.Equal<Type>(typeof(TestRecord), actual[0].ObjectType);

            Assert.IsType<XmlDataObject>(actual[1]);
            Assert.Equal<HttpCacheability>(HttpCacheability.Public, actual[1].Cacheability.Value);
            Assert.Equal<HttpStatusCode>(HttpStatusCode.OK, actual[1].Status.Value);
            Assert.Equal<Type>(typeof(TestRecord), actual[1].ObjectType);
        }

        [Fact]
        public void op_Add_FileInfoNotFound()
        {
            Assert.Throws<FileNotFoundException>(() => new XmlDataObjectCollection().Add(new FileInfo(Token.New() + ".object.xml")));
        }

        [Fact]
        public void op_Add_FileInfoNull()
        {
            Assert.Throws<ArgumentNullException>(() => new XmlDataObjectCollection().Add(null as FileInfo));
        }

        [Fact]
        public void op_Load_DirectoryInfo()
        {
            XmlDataObjectCollection actual = XmlDataObjectCollection.Load(new DirectoryInfo(@"Data"));

            Assert.Equal<int>(2, actual.Count);

            Assert.IsType<XmlDataObject>(actual[0]);
            Assert.Equal<HttpCacheability>(HttpCacheability.Public, actual[0].Cacheability.Value);
            Assert.Equal<HttpStatusCode>(HttpStatusCode.NotFound, actual[0].Status.Value);
            Assert.Equal<Type>(typeof(TestRecord), actual[0].ObjectType);

            Assert.IsType<XmlDataObject>(actual[1]);
            Assert.Equal<HttpCacheability>(HttpCacheability.Public, actual[1].Cacheability.Value);
            Assert.Equal<HttpStatusCode>(HttpStatusCode.OK, actual[1].Status.Value);
            Assert.Equal<Type>(typeof(TestRecord), actual[1].ObjectType);
        }

        [Fact]
        public void op_Load_DirectoryInfoNotFound()
        {
            Assert.Throws<FileNotFoundException>(() => XmlDataObjectCollection.Load(new DirectoryInfo(Token.New())));
        }

        [Fact]
        public void op_Load_DirectoryInfoNull()
        {
            Assert.Throws<ArgumentNullException>(() => XmlDataObjectCollection.Load(null as DirectoryInfo));
        }

        [Fact]
        public void op_Load_FileInfo()
        {
            XmlDataObjectCollection actual = XmlDataObjectCollection.Load(new FileInfo(@"Data\Record.Test.object.xml"));

            Assert.Equal<int>(2, actual.Count);

            Assert.IsType<XmlDataObject>(actual[0]);
            Assert.Equal<HttpCacheability>(HttpCacheability.Public, actual[0].Cacheability.Value);
            Assert.Equal<HttpStatusCode>(HttpStatusCode.NotFound, actual[0].Status.Value);
            Assert.Equal<Type>(typeof(TestRecord), actual[0].ObjectType);

            Assert.IsType<XmlDataObject>(actual[1]);
            Assert.Equal<HttpCacheability>(HttpCacheability.Public, actual[1].Cacheability.Value);
            Assert.Equal<HttpStatusCode>(HttpStatusCode.OK, actual[1].Status.Value);
            Assert.Equal<Type>(typeof(TestRecord), actual[1].ObjectType);
        }

        [Fact]
        public void op_Load_FileInfoNotFound()
        {
            Assert.Throws<FileNotFoundException>(() => XmlDataObjectCollection.Load(new FileInfo(Token.New() + ".object.xml")));
        }

        [Fact]
        public void op_Load_FileInfoNull()
        {
            Assert.Throws<ArgumentNullException>(() => XmlDataObjectCollection.Load(null as FileInfo));
        }

        [Fact]
        public void op_Load_IXPathNavigable()
        {
            XmlDocument xml = new XmlDocument();
            xml.Load(@"Data\Record.Test.object.xml");

            XmlDataObjectCollection actual = XmlDataObjectCollection.Load(xml);

            Assert.Equal<int>(2, actual.Count);

            Assert.IsType<XmlDataObject>(actual[0]);
            Assert.Equal<HttpCacheability>(HttpCacheability.Public, actual[0].Cacheability.Value);
            Assert.Equal<HttpStatusCode>(HttpStatusCode.NotFound, actual[0].Status.Value);
            Assert.Equal<Type>(typeof(TestRecord), actual[0].ObjectType);

            Assert.IsType<XmlDataObject>(actual[1]);
            Assert.Equal<HttpCacheability>(HttpCacheability.Public, actual[1].Cacheability.Value);
            Assert.Equal<HttpStatusCode>(HttpStatusCode.OK, actual[1].Status.Value);
            Assert.Equal<Type>(typeof(TestRecord), actual[1].ObjectType);
        }

        [Fact]
        public void op_Load_IXPathNavigableNull()
        {
            Assert.Throws<ArgumentNullException>(() => XmlDataObjectCollection.Load(null as IXPathNavigable));
        }
    }
}